/*
 * freessmcfg.cpp - configure FreeSSM dialog
 *
 * Copyright (C) 2008-2010 Comer352l
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "freessmcfg.h"
#include "ui_freessmcfg.h"

freessmcfg::freessmcfg(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::freessmcfg)
{
    ui->setupUi(this);
    messages = new myMessage(0);
    settings = new QSettings("carpc", "freessm", this);
    settings->setPath(QSettings::IniFormat,QSettings::UserScope,"carpc");
    newinterfacefilename = settings->value("interface").toString();
    QString ifacetype = settings->value("interfacetype").toString();
    if (ifacetype == QString::number(AbstractDiagInterface::interface_J2534)) {
        newinterfacetype = AbstractDiagInterface::interface_J2534;
    } else {
        newinterfacetype = AbstractDiagInterface::interface_serialPassThrough;
    }
    int if_name_index = -1;
    if (newinterfacetype == AbstractDiagInterface::interface_J2534) // J2534-Pass-Through
    {
        ui->interfaceType_comboBox->setCurrentIndex(1);
        on_interfaceType_comboBox_activated(1); // NOTE: fills _J2534libraryPaths, changes _newinterfacefilename
        if_name_index = _J2534libraryPaths.indexOf(newinterfacefilename);
    }
    else	// Serial Pass-Through
    {
        ui->interfaceType_comboBox->setCurrentIndex(0);
        on_interfaceType_comboBox_activated(0); // NOTE: fills _J2534libraryPaths, changes _newinterfacefilename
        if_name_index = ui->interfaceName_comboBox->findText(newinterfacefilename);
    }
    if (if_name_index >= 0)
    {
        ui->interfaceName_comboBox->setCurrentIndex(if_name_index);
        on_interfaceName_comboBox_activated(if_name_index);
    }
    else
    {
        if (ui->interfaceName_comboBox->count() > 0)	// if min. 1 device available
        {
            ui->interfaceName_comboBox->setCurrentIndex(0);
            on_interfaceName_comboBox_activated(0);
        }
        else
        {
            newinterfacefilename = "";
        }
    }
}

freessmcfg::~freessmcfg()
{
    settings->setValue("interface",newinterfacefilename.toAscii());
    settings->setValue("interfacetype",QString::number(newinterfacetype).toAscii());
    delete ui;
}

void freessmcfg::on_interfaceType_comboBox_activated(int index)
{
    ui->interfaceName_comboBox->clear();
    _J2534libraryPaths.clear();
    newinterfacefilename = "";
    QStringList deviceNames;
    if (index == 0)		// Serial Pass-Through
    {
        newinterfacetype = AbstractDiagInterface::interface_serialPassThrough;
        std::vector<std::string> portlist = serialCOM::GetAvailablePorts();
        for (unsigned int k=0; k<portlist.size(); k++)
            deviceNames.push_back(QString::fromStdString(portlist.at(k)));
    }
    else if (index == 1)	// J2534-Pass-Through
    {
        newinterfacetype = AbstractDiagInterface::interface_J2534;
        std::vector<J2534Library> J2534libs = J2534_API::getAvailableJ2534Libs();
        for (unsigned int k=0; k<J2534libs.size(); k++)
        {
            deviceNames.push_back(QString::fromStdString(J2534libs.at(k).name));
            _J2534libraryPaths.push_back(QString::fromStdString(J2534libs.at(k).path));
        }
    }
    if (deviceNames.size())
    {
        ui->interfaceName_comboBox->addItems(deviceNames);
        ui->interfaceName_comboBox->setCurrentIndex(0);
        on_interfaceName_comboBox_activated(0);
    }
    ui->interfaceName_comboBox->setEnabled(deviceNames.size());
    ui->testinterface_pushButton->setEnabled(deviceNames.size());
    // NOTE: Never put anything else than a device-file into the interfaceName_comboBox !
}


void freessmcfg::on_interfaceName_comboBox_activated(int index)
{
    if ((index < 0) || (index >= ui->interfaceName_comboBox->count()))
        newinterfacefilename = "";
    else
    {
        if (newinterfacetype == AbstractDiagInterface::interface_J2534)
        {
            if (index < _J2534libraryPaths.size())
                newinterfacefilename = _J2534libraryPaths.at(index);
            else	// should never happen
                newinterfacefilename = "";
        }
        else
            newinterfacefilename = ui->interfaceName_comboBox->currentText();
    }
}


void freessmcfg::on_testinterface_pushButton_pressed()
{
    // PREPARE INTERFACE:
    AbstractDiagInterface *diagInterface = NULL;
    if (newinterfacetype == AbstractDiagInterface::interface_serialPassThrough)
    {
        diagInterface = new SerialPassThroughDiagInterface;
    }
    else if (newinterfacetype == AbstractDiagInterface::interface_J2534)
    {
        diagInterface = new J2534DiagInterface;
    }
    else
    {
        messages->exec(2,"The selected interface is not supported !");
        messages->exec(2,"Internal error:\nThe interface test for the selected interface is not yet implemented.\n=> Please report this as a bug.");
        return;
    }
    // OPEN INTERFACE:
    if (!diagInterface->open(newinterfacefilename.toStdString()))
    {
        messages->exec(2,"Couldn't open the diagnostic interface !\nPlease make sure that the device is not in use by another application.");
        delete diagInterface;
        return;
    }
    // DISPLAY INFO MESSAGE:
    messages->exec(3,"Please connect diagnostic interface to the vehicles\ndiagnostic connector and switch ignition on.");
    if (messages->result)
    {
        myProgressbar waitmsgbox(0,"Testing interface... Please wait !");
        // START INTERFACE-TEST:
        bool icresult = false;
        bool retry = true;
        bool SSM1configOK = false;
        bool SSM2configOK = false;
        while (retry && !icresult)
        {
            char data = 0;
            // OUTPUT WAIT MESSAGE:
            waitmsgbox.start();
            // SSM2:
            SSM2configOK = diagInterface->connect(AbstractDiagInterface::protocol_SSM2);
            if (SSM2configOK)
            {
                SSMP2communication *SSMP2com = new SSMP2communication(diagInterface, 0x10);
                unsigned int addr = 0x61;
                icresult = SSMP2com->readMultipleDatabytes('\x0', &addr, 1, &data);
                delete SSMP2com;
                diagInterface->disconnect();
            }
            // SSM1:
            SSM1configOK = diagInterface->connect(AbstractDiagInterface::protocol_SSM1);
            if (SSM1configOK)
            {
                if (!icresult)
                {
                    SSMP1communication *SSMP1com = new SSMP1communication(diagInterface, SSM1_CU_Engine);
                    icresult = SSMP1com->readAddress(0x00, &data);
                    if (!icresult)
                    {
                        SSMP1com->selectCU(SSM1_CU_Transmission);
                        icresult = SSMP1com->readAddress(0x00, &data);
                        delete SSMP1com;
                    }
                }
                diagInterface->disconnect();
            }
            // CLOSE WAIT MESSAGE:
            waitmsgbox.stop();
            // DISPLAY TEST RESULT:
            QString resultText;
            if (icresult)
                resultText = tr("Interface test successful !");
            else
                resultText = tr("Interface test failed !");
            if (!SSM1configOK && !SSM2configOK)	// => test must have failed
            {
                if (newinterfacetype == AbstractDiagInterface::interface_serialPassThrough)
                    resultText += "\n\n" + tr("The selected serial port can not be configured for the SSM1- and SSM2-protocol.");
                else
                    resultText += "\n\n" + tr("The selected interface does not support the SSM1- and SSM2-protocol.");
            }
            else if (!icresult)
            {
                resultText += "\n\n" + tr("Please make sure that the interface is connected properly and ignition is switched ON.");
            }
            if (!SSM1configOK || !SSM2configOK)
            {
                resultText += "\n\n" + tr("WARNING:");
                if (!SSM1configOK)
                {
                    if (newinterfacetype == AbstractDiagInterface::interface_serialPassThrough)
                        resultText += '\n' + tr("The selected serial port can not be configured for the SSM1-protocol.");
                    else
                        resultText += '\n' + tr("The selected interface does not support the SSM1-protocol.");
                }
                else if (!SSM2configOK)
                {
                    if (newinterfacetype == AbstractDiagInterface::interface_serialPassThrough)
                        resultText += '\n' + tr("The selected serial port can not be configured for the SSM2-protocol.");
                    else
                        resultText += '\n' + tr("The selected interface does not support the SSM2-protocol.");
                }
            }
            if (icresult) {
                messages->exec(1,resultText.toLocal8Bit());
                retry = true;
            } else {
                messages->exec(3,resultText.toLocal8Bit());
            }
            if (!icresult && (!messages->result))
                retry = false;
            else
                retry = true;
        }
    }
    // CLOSE INTERFACE:
    if (!diagInterface->close())
        messages->exec(2,"Couldn't close the diagnostic interface !");
    delete diagInterface;
}

